' This program exported from BASIC Anywhere Machine (Version [5.2.3].[2024.09.09.00.00]) on 2025.03.01 at 19:07 (Coordinated Universal Time) ' This program by Charlie Veniot is a port and mod of a QB64 program by b+ _Title "Isometric Bouncing Ball Simulation Claude per issues37" ' 2025-03-01 wow ' Creates a 3D-like environment with balls dropping onto an isometric grid ' and bouncing in random directions before falling off the edge SCREEN _NEWIMAGE( 760, 580, 27 ) _TITLE "Isometric Bouncing Ball Simulation" _INITAUDIO CONST GRID_SIZE = 400 ' Size of the isometric grid CONST GRAVITY = 0.2 ' Gravity constant CONST BOUNCE_FACTOR = 0.8 ' Energy retained after bounce CONST MAX_BALLS = 5 ' Maximum number of active balls CONST SPAWN_RATE = 3 ' Frames between new ball spawns CONST X_ADJ = - 260, Y_ADJ = - 160, WHITE = _RGB32( 255, 255, 255 ) ' Ball properties TYPE BallType x AS SINGLE ' 3D coordinates y AS SINGLE z AS SINGLE vx AS SINGLE ' Velocity components vy AS SINGLE vz AS SINGLE size AS SINGLE ' Ball size in pixels bcolor AS ULONG ' Ball color active AS INTEGER ' 1 = active, 0 = inactive END TYPE DIM balls( 1 TO MAX_BALLS ) AS BallType DIM frameCounter AS INTEGER DIM ballsCreated AS INTEGER ' Origin of isometric grid (center of screen, base level) CONST ORIGIN_X = 640, ORIGIN_Y = 500 DECLARE SUB CreateNewBall DECLARE SUB DrawIsometricGrid DECLARE SUB ProcessBalls DECLARE SUB Convert3DToScreen (x AS SINGLE, y AS SINGLE, z AS SINGLE, screenX AS INTEGER, screenY AS INTEGER) DECLARE Sub Line3D (x1 AS SINGLE, y1 AS SINGLE, z1 AS SINGLE, x2 AS SINGLE, y2 AS SINGLE, z2 AS SINGLE, c AS ULONG) ' Main program loop DO CLS CALL DrawIsometricGrid CALL ProcessBalls ' Spawn new balls at regular intervals frameCounter = frameCounter + 1 IF frameCounter MOD SPAWN_RATE = 0 _ AND ballsCreated < MAX_BALLS _ THEN CreateNewBall SLEEP 0.015 LOOP END SUB CreateNewBall DIM i AS INTEGER ' Find an available slot for a new ball FOR i = 1 TO MAX_BALLS IF balls(i).active = 0 THEN ' Initialize ball properties balls(i).x = 0 : balls(i).y = 0 : balls(i).z = 300 balls(i).vx = ( RND - 0.5 ) * 2 ' Small random initial velocity balls(i).vy = ( RND - 0.5 ) * 2 : balls(i).vz = 0 balls(i).size = 5 + INT( RND * 8 ) balls(i).bcolor = _RGB32( 128 + RND * 127, 128 + RND * 127, 128 + RND * 127) balls(i).active = 1 ballsCreated = ballsCreated + 1 i = MAX_BALLS + 1 END IF NEXT i END SUB ' Draw isometric grid SUB DrawIsometricGrid DIM AS INTEGER x, y, screenX, screenY, gridStep gridStep = 50 ' Space between grid lines ' Draw grid lines FOR x = ( -GRID_SIZE / 2 ) TO ( GRID_SIZE / 2 ) STEP gridStep ' Draw line along the x-axis CALL Line3D( x, ( -GRID_SIZE / 2 ), 0, x, ( GRID_SIZE / 2 ), 0, WHITE ) ' Draw line along the y-axis CALL Line3D( ( - GRID_SIZE / 2 ), x, 0, ( GRID_SIZE / 2 ), x, 0, WHITE ) NEXT x END SUB ' Process and draw all active balls SUB ProcessBalls DIM AS INTEGER i, screenX, screenY FOR i = 1 TO MAX_BALLS IF balls(i).active = 1 THEN ' Apply gravity balls(i).vz = balls(i).vz - GRAVITY ' Update position balls(i).x = balls(i).x + balls(i).vx balls(i).y = balls(i).y + balls(i).vy balls(i).z = balls(i).z + balls(i).vz ' Check for collision with the floor IF balls(i).z <= 0 THEN ' Bounce on the grid balls(i).z = 0 balls(i).vz = -balls(i).vz * BOUNCE_FACTOR IF balls(i).vz > 0.15 THEN SOUND (300 - balls(i).size * 20 ), 1 ' Add random horizontal movement after bounce balls(i).vx = balls(i).vx + ( RND - 0.5 ) * 3 balls(i).vy = balls(i).vy + ( RND - 0.5 ) * 3 END IF ' Check if ball is outside grid boundaries IF ABS( balls(i).x ) > GRID_SIZE / 2 _ OR ABS( balls(i).y ) > GRID_SIZE / 2 _ THEN ' Reset ball position to top balls(i).x = 0 balls(i).y = 0 balls(i).z = 300 balls(i).vx = ( RND - 0.5 ) * 2 balls(i).vy = ( RND - 0.5 ) * 2 balls(i).vz = 0 END IF ' Convert 3D coordinates to isometric screen position ' and draw the ball CALL Convert3DToScreen( balls(i).x, balls(i).y, balls(i).z, screenX, screenY ) CIRCLE( screenX, screenY ), balls(i).size, balls(i).bcolor PAINT( screenX, screenY ), balls(i).bcolor, balls(i).bcolor END IF NEXT i END SUB ' Convert 3D coordinates to isometric screen coordinates SUB Convert3DToScreen( x AS SINGLE, y AS SINGLE, z AS SINGLE, screenX AS INTEGER, screenY AS INTEGER ) ' Isometric projection factors CONST ISO_X1 = 0.866 ' cos(30?) CONST ISO_X2 = 0.866 ' cos(30?) CONST ISO_Y1 = 0.5 ' sin(30?) CONST ISO_Y2 = -0.5 ' -sin(30?) ' Convert 3D to isometric 2D screenX = ORIGIN_X + X_ADJ + ( x * ISO_X1 + y * ISO_X2 ) screenY = ORIGIN_Y + Y_ADJ + ( x * ISO_Y1 + y * ISO_Y2 ) - z END SUB ' Draw a line in 3D space SUB Line3D( x1 AS SINGLE, y1 AS SINGLE, z1 AS SINGLE, x2 AS SINGLE, y2 AS SINGLE, z2 AS SINGLE, c AS ULONG ) DIM AS INTEGER sx1, sy1, sx2, sy2 ' Convert 3D points to screen coordinates CALL Convert3DToScreen( x1, y1, z1, sx1, sy1 ) CALL Convert3DToScreen( x2, y2, z2, sx2, sy2 ) ' Draw the line LINE ( sx1, sy1 ) - ( sx2, sy2 ), c END SUB